package com.wwj.tem.utils;

import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author: wwj
 * @create: 2024/7/24 - 22:05
 * Description: Redis 实用程序
 */
@Slf4j
@Component
public class RedisUtils {
	
	private static StringRedisTemplate stringRedisTemplate;
	
	@PostConstruct
	public void init() {
		stringRedisTemplate = SpringUtil.getBean(StringRedisTemplate.class);
	}
	
	private static final String LUA_INCR_EXPIRE = "local key,ttl=KEYS[1],ARGV[1] \n" + " \n" + "if redis.call('EXISTS',key)==0 then   \n" + "  redis.call('SETEX',key,ttl,1) \n" + "  return 1 \n" + "else \n" + "  return tonumber(redis.call('INCR',key)) \n" + "end ";
	
	public static Long inc(String key, int time, TimeUnit unit) {
		RedisScript<Long> redisScript = new DefaultRedisScript<>(LUA_INCR_EXPIRE, Long.class);
		return stringRedisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(unit.toSeconds(time)));
	}
	
	public static Boolean zIsMember(String key, Object value) {
		return Objects.nonNull(stringRedisTemplate.opsForZSet().score(key, value.toString()));
	}
	
	public static void zRemove(String key, Object value) {
		zRemove(key, value.toString());
	}
	
	public static void zRemove(String key, String value) {
		stringRedisTemplate.opsForZSet().remove(key, value);
	}
	
	/**
	 * 添加元素,有序集合是按照元素的score值由小到大排列
	 *
	 * @param key   钥匙
	 * @param value 价值
	 * @param score 得分
	 */
	public static void zAdd(String key, String value, double score) {
		stringRedisTemplate.opsForZSet().add(key, value, score);
	}
	
	public static void zAdd(String key, Object value, double score) {
		zAdd(key, value.toString(), score);
	}
	
	/**
	 * 设置键值对并指定过期时间
	 * @param key 键
	 * @param value 值
	 * @param timeout 过期时间
	 * @param timeUnit 时间单位
	 */
	public static void setWithExpire(String key, String value, long timeout, TimeUnit timeUnit) {
		stringRedisTemplate.opsForValue().set(key, value, timeout, timeUnit);
	}
	
	/**
	 * 获取键对应的值
	 * @param key 键
	 * @return 值
	 */
	public static String get(String key) {
		return stringRedisTemplate.opsForValue().get(key);
	}
	
	/**
	 * 删除指定键
	 * @param key 键
	 * @return 是否删除成功
	 */
	public static Boolean delete(String key) {
		return stringRedisTemplate.delete(key);
	}
}
